package net.jalbum.filters;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import net.jalbum.filterManager.FilterProperties.FilterCategory;
import se.datadosen.jalbum.Msg;

public class PixelateFilterPlugin extends BasicFilter {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6592860195353596506L;
	protected int pixelSize = 5;
	protected PixelateControl pixelateControl;

	public PixelateFilterPlugin() {
		this.name = Msg.getString(this, "filters.pixelate.name");
		this.shortName = Msg.getString(this, "filters.pixelate.shortName");
		this.icon = new ImageIcon(this.getClass().getResource("res/mosaic.png"));
		this.author = "David Fichtmueller";
		this.version = "1.0";
		this.description = Msg.getString(this, "filters.pixelate.description");
		this.category = FilterCategory.FUN;
		this.prescale = false;
		this.postscale = true;
		this.pixelateControl = new PixelateControl(this);
	}

	@Override
	public JPanel getControls() {
		return this.pixelateControl;
	}

	/**
	 * We never touch the original image so avoid cloning
	 * @param bi
	 * @return
	 */
	@Override
	protected BufferedImage cloneBufferedImage(final BufferedImage bi) {
		return bi;
	}

	@Override
	public BufferedImage renderImage(final BufferedImage bi) {
		return this.pixelateImage(bi, this.pixelSize);
	}

	public BufferedImage pixelateImage(final BufferedImage bi, int pixelSize) {
		if (pixelSize == 0) {
			pixelSize = 1;
		}

		final int width = bi.getWidth();
		final int height = bi.getHeight();
		final BufferedImage out = new BufferedImage(width, height, bi.getType());

		int rasterWidth = width / pixelSize;
		if (width % pixelSize > 0) {
			rasterWidth++;
		}
		int rasterHeight = height / pixelSize;
		if (height % pixelSize > 0) {
			rasterHeight++;
		}

		int alpha, r, g, b, nextX, nextY, rgb, posX, posY;
		for (int x = 0; x < rasterWidth; x++) {
			for (int y = 0; y < rasterHeight; y++) {
				alpha = 0;
				r = 0;
				g = 0;
				b = 0;

				nextX = Math.min(pixelSize, width - (x * pixelSize));
				nextY = Math.min(pixelSize, height - (y * pixelSize));

				for (posX = x * pixelSize; posX < x * pixelSize + nextX; posX++) {
					for (posY = y * pixelSize; posY < y * pixelSize + nextY; posY++) {
						try {
							rgb = bi.getRGB(posX, posY);
						} catch (final RasterFormatException e) {
							rgb = 0;
						}

						// get the rgb-values
						alpha = alpha + ((rgb & 0xff000000) >> 24);
						r = r + ((rgb & 0x00ff0000) >> 16);
						g = g + ((rgb & 0x0000ff00) >> 8);
						b = b + ((rgb & 0x000000ff));
					}
				}

				// figure out medium color
				alpha = alpha / (nextX * nextY);
				r = r / (nextX * nextY);
				g = g / (nextX * nextY);
				b = b / (nextX * nextY);

				// make new color
				rgb = ((alpha & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);

				// write it for all pixels
				for (posX = x * pixelSize; posX < x * pixelSize + nextX; posX++) {
					for (posY = y * pixelSize; posY < y * pixelSize + nextY; posY++) {
						try {
							out.setRGB(posX, posY, rgb);
						} catch (final RasterFormatException e) {
						}
					}
				}
			}
		}

		return out;
	}

	@Override
	public void paint(final Graphics g) {
		// draw the current version of the image
		super.paint(g);
	}

	public int getPixelSize() {
		return this.pixelSize;
	}

	public void setPixelSize(final int pixelSize) {
		this.pixelSize = pixelSize;
	}
}
